package run.iget.security.util;

import cn.hutool.core.util.StrUtil;
import run.iget.framework.cache.CacheUtils;
import run.iget.framework.event.EventPublishUtils;
import run.iget.security.bean.AuthUser;
import run.iget.security.bean.SafeAuthUser;
import run.iget.security.constant.SecurityConst;
import run.iget.security.event.AuthEventEnums;
import run.iget.security.event.SafeAuthEvent;

import java.util.Objects;
import java.util.Set;

/**
 * 代码千万行，注释第一行，注释不规范，迭代两行泪
 * ---------------类描述-----------------
 * 登录工具类
 * ---------------类描述-----------------
 *
 * @author 大周
 * @since 2022/8/24 14:41
 */
public final class LoginUtils {

    private final static ThreadLocal<SafeAuthUser> THREAD_LOCAL_LOGIN_USER = new ThreadLocal<>();

    public static void set(SafeAuthUser loginUser) {
        THREAD_LOCAL_LOGIN_USER.set(loginUser);
    }

    public static SafeAuthUser get() {
        return THREAD_LOCAL_LOGIN_USER.get();
    }

    public static void clear() {
        THREAD_LOCAL_LOGIN_USER.remove();
    }

    public static void login(SafeAuthUser loginUser) {
        loginUser.genToken(SecurityConst.TOKEN_EXPIRE_SECONDS);
        CacheUtils.set(loginUser.getToken(), loginUser, SecurityConst.TOKEN_EXPIRE_SECONDS);
        CacheUtils.set(loginUser.getPartitionOfId(), loginUser, SecurityConst.TOKEN_EXPIRE_SECONDS);
        // 发布登录事件
        EventPublishUtils.publish(new SafeAuthEvent(loginUser, AuthEventEnums.LOGIN));
    }

    public static Set<Long> getRoleIds() {
        SafeAuthUser safeAuthUser = get();
        return Objects.isNull(safeAuthUser) ? null : safeAuthUser.getRoles();
    }

    public static Set<Long> getDepartmentIds() {
        SafeAuthUser safeAuthUser = get();
        return Objects.isNull(safeAuthUser) ? null : safeAuthUser.getDepartments();
    }

    public static SafeAuthUser get(Long id) {
        return get(null, id);
    }

    public static SafeAuthUser get(String partition, Long id) {
        if (Objects.isNull(id)) {
            return null;
        }
        String partitionOfId = getPartitionOfId(partition, id);
        if (Objects.isNull(partitionOfId)) {
            return null;
        }
        return (SafeAuthUser) CacheUtils.get(partitionOfId);
    }

    /**
     * 获取根据分区的id
     *
     * @param partition
     * @param id
     * @return
     */
    private static String getPartitionOfId(String partition, Long id) {
        if (StrUtil.isBlank(partition)) {
            return String.valueOf(id);
        }
        return partition + "_" + id;
    }

    /**
     * 根据id判断是否已经登录
     *
     * @param id 登录的id标识
     * @return
     */
    public static boolean isLogin(Long id) {
        return Objects.nonNull(get(id));
    }

    /**
     * 根据id判断是否已经登录
     *
     * @param partition 多账号体现下的分区标志
     * @param id        登录的id标识
     * @return
     */
    public static boolean isLogin(String partition, Long id) {
        return Objects.nonNull(get(partition, id));
    }

    public static SafeAuthUser getByToken(String token) {
        if (StrUtil.isBlank(token)) {
            return null;
        }
        return (SafeAuthUser) CacheUtils.get(token);
    }

    public static Long getId() {
        AuthUser userDetail = get();
        return Objects.nonNull(userDetail) ? userDetail.getId() : null;
    }

    public static void loginOut() {
        SafeAuthUser authUser = get();
        if (Objects.isNull(authUser)) {
            return;
        }
        CacheUtils.remove(authUser.getPartitionOfId());
        CacheUtils.remove(authUser.getToken());
        // 发布退出事件
        EventPublishUtils.publish(new SafeAuthEvent(authUser, AuthEventEnums.LOGOUT));
    }
}
